<?php
class Delivery_Model_Carrito 
{
		
	private $session;
	public $productos = array();
	public $promociones = array();
	
	private static $_instance = null;
	
    public static function getInstance()
    {
        if (self::$_instance === null) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
	
    public function __clone()
	{
	}
    
	private function __construct()
	{
		$this->session = Zend_Registry::get('session');

		
		try {
		
		if (isset($this->session->productosCarrito) && !empty($this->session->productosCarrito)){		
			
			$keys = array_keys($this->session->productosCarrito);
			$ids = $this->_getIds( $keys );
			
			$mapper = Delivery_Model_Factory::mapper( 'Productos' );
			
			$productos = $mapper->getByIds( $ids );
			$mapper->loadNegocio( $productos );
			$mapper->loadCategoria( $productos );
			$mapper->loadOpciones( $productos );
			
			foreach ($this->session->productosCarrito as $productoKey => $cantidad){
				
				if ( strpos($productoKey, "-") ){
					list( $id, $opcionesIds, $opcionesCantidades) = explode("-", $productoKey);
				} else {
					list( $id, $opcionesIds, $opcionesCantidades) = array( $productoKey, null, null);
				}
				
				
				$productoPedido = new Delivery_Model_ProductoPedido( (array) $productos[$id]);
				$productoPedido->cantidad = $cantidad;
				$productoPedido->setNegocio( $productos[$id]->getNegocio() );
				$productoPedido->setCategoria( $productos[$id]->getCategoria() );
				$productoPedido->setOpciones( $productos[$id]->getOpciones() );
				
				
				
				if( $opcionesIds ){
				    
				    if ( strpos($opcionesIds, ":") ){
    					$combinaciones = array_combine(
    						explode( ':', $opcionesIds),
    						explode( ':', $opcionesCantidades)
    					);
				    } else {
				        $combinaciones = array_combine(
    						array( $opcionesIds),
    						array( $opcionesCantidades)
    					);
				    }
					
					$productoPedido->setCombinaciones( $combinaciones );
					
				}
				
				$this->productos[$productoKey] = $productoPedido;
				
			}
			
			
			
		}

		if (isset($this->session->promocionesCarrito) && !empty($this->session->promocionesCarrito)){		
			
			$keys = array_keys($this->session->promocionesCarrito);
			
			
			$ids = $this->_getIds( $keys );
			
			$mapper = Delivery_Model_Factory::mapper( 'Promociones' );
			$promociones = $mapper->getByIds( $ids );
			
			$mapper->loadNegocio( $promociones );
			$mapper->loadItems( $promociones );
			
			foreach ($this->session->promocionesCarrito as $promoKey => $cantidad){
				
				if ( strpos($promoKey, "-") ){
					list( $id, $pro, $cant) = explode("-", $promoKey);
				} else {
					list( $id, $pro, $cant) = array( $promoKey, null, null);
				}
				
				
				$promocion = new Delivery_Model_PromocionPedida( (array) $promociones[$id]);
				$promocion->setNegocio( $promociones[$id]->getNegocio() );
				$promocion->setItems( $promociones[$id]->getItems() );
				$promocion->cantidad = $cantidad;
				
				if( $pro ){
				    $promocion->productosIds = explode(":", $pro);
					$promocion->productosCantidades = array_combine( $promocion->productosIds, explode(":", $cant));
					$promocion->productos = $promocion->productosCantidades;
				}
				
				
				
				$this->promociones[$promoKey] = $promocion;
				
			}
			
			
		}	
		
		}catch( Zend_Exception $e) {
		    //TODO Log 
//		    throw $e;
		}
	}	
	
	public function __destruct()
	{
		/**
		 * Guardo los productos en la session
		 */
		if ( !empty ($this->productos) ){	

			$this->session->productosCarrito = array();
			
			foreach ($this->productos as $productoKey=>$productoPedido){			
				$this->session->productosCarrito[$productoKey] = $productoPedido->cantidad;		
			}
			
		} else {
			unset($this->session->productosCarrito);		
		}	
		
		/**
		 * Guardo las promociones en la session
		 */
		if ( !empty ($this->promociones) ){	

			$this->session->promocionesCarrito = array();
			
			foreach ($this->promociones as $promoKey=>$promocion){			
				$this->session->promocionesCarrito[$promoKey] = $promocion->cantidad;		
			}
			
		} else {
			unset($this->session->promocionesCarrito);		
		}
		
	}	
	
	
	public function isEmpty()
	{
		return empty( $this->productos) AND empty( $this->promociones) ;
	}
	
	public function agregar ( $idProducto , $cantidad, $opciones)
	{
		$cliente = null;
		
		$mapper = Delivery_Model_Factory::mapper( 'ProductosPedido' );
		$mapper2 = Delivery_Model_Factory::mapper( 'Productos' );
		$producto = $mapper->getByParentId($idProducto);
		
		$mapper2->loadOpciones( $producto );
		
		$producto->setCombinaciones( $opciones );
		
		$productoKey = $producto->getKey();
		
		$disponible = $this->disponible( $producto );
		
		if ($disponible < 1){
			throw new Delivery_Model_Exception( Delivery_Model_Exception::PRODUCT_NOT_STOCK);
		}
		
		if ( $cantidad > 0 ){
			
			if (isset($this->productos[$productoKey])){
				
				$this->productos[$productoKey]->cantidad+=$cantidad;				
			
			} else {
			
				$producto->cantidad = $cantidad;
				$this->productos[$productoKey] = $producto;
			}										
			
		} else {
			
			if (isset($this->productos[$productoKey])){
				$this->eliminarProducto( $productoKey );		
			}				
		}
		
		return array(
			'precioParcial' => number_format($producto->getPrecioTotal( $cliente ), 2),
			'precioTotal' => number_format($this->getTotalNegocio( $producto->idNegocio, $cliente ), 2),
			'cantidadTotal' => $this->cantidadTotal( )
		);
		
	}
	
	public function agregarPromocion ( $idPromocion , $cantidad, $productos = null)
	{
		$mapper = Delivery_Model_Factory::mapper( 'PromocionesPedido' );
		$mapper2 = Delivery_Model_Factory::mapper( 'Promociones' );
		$promocion = $mapper->getByParentId( $idPromocion );
		
		$mapper2->loadItems( $promocion );
		
		$promocion->setCombinaciones($productos);
		
		/**
		 * No puedo usar como llave el ID de la promo, 
		 * ya que la misma promo podria tener combinaciones de productos diferentes.
		 */
		$promoKey = $promocion->getKey();
		
		if ( $cantidad > 0 ){
			
			if (isset( $this->promociones[$promoKey] )){
				
				$this->promociones[$promoKey]->cantidad+=$cantidad;
			
			} else {
			
				$promocion->cantidad = $cantidad;
				$this->promociones[$promoKey] = $promocion;
			}										
			
		} else {
			
			if (isset($this->promociones[$promoKey])){
				$this->eliminarPromocion( $promoKey );		
			}				
		}
		
		return array(
			'precioParcial' => number_format($promocion->getPrecioTotal(), 2),
			'precioTotal' => number_format($this->getTotalNegocio( $promocion->idNegocio ), 2),
			'cantidadTotal' => $this->cantidadTotal( )
		);
		
	}
	
	public function disponible ( $producto )
	{
		$n = isset ($this->productos[$producto->idProducto]) ? $this->productos[$producto->idProducto]->cantidad: 0;
		
		return (int) $producto->cantidadDisponible - $n;
	} 
	
	public function cantidad ( $producto )
	{
		return
			isset ($this->productos[$producto->idProducto]) ?
			$this->productos[$producto->idProducto]->cantidad:
			0;	
	} 
	
	public function cantidadTotal()
	{
		$total = 0;
		
		foreach ( $this->productos as $producto ){
			$total+= $producto->cantidad;
		}
		foreach ( $this->promociones as $promocion ){
			$total+= $promocion->cantidad;
		}
		
		return $total;
	}
	
	public function agruparPorNegocio( )
	{
		$p = array();
		
		foreach ($this->productos as $producto){
		
			$negocio = $producto->getNegocio();
			$idNegocio = $negocio->idNegocio;
			
			if ( empty( $p[$idNegocio] ) ){
				$p[$idNegocio] = array('negocio' => $negocio, 'productos' =>array(), 'promociones' =>array(), 'total' =>0);
			}
			
			$p[$idNegocio]['productos'][] = $producto;
			$p[$idNegocio]['total']+= $producto->getPrecioTotal();
		
		}
		
		foreach ($this->promociones as $promocion){
		
			$negocio = $promocion->getNegocio();
			$idNegocio = $negocio->idNegocio;
			
			if ( empty( $p[$idNegocio] ) ){
				$p[$idNegocio] = array('negocio' => $negocio, 'productos' =>array(), 'promociones' =>array(), 'total' =>0);
			}
			
			$p[$idNegocio]['promociones'][] = $promocion;
			$p[$idNegocio]['total']+= $promocion->getPrecioTotal();
		
		}
		
		return $p;
	}
	
	public function vaciar( $idNegocio = null )
	{
		foreach($this->productos as $productoKey => $producto){
		
			if ( $idNegocio == $producto->idNegocio){
			
				$this->eliminarProducto( $productoKey );				
				
			}
		}	

		foreach($this->promociones as $prodmoKey => $promocion){
		
			if ( $idNegocio == $promocion->idNegocio){
			
				$this->eliminarPromocion( $prodmoKey );				
				
			}
		}	
	}
	
	public function eliminarProducto( $productoKey )
	{
		
		if ( ! isset($this->productos[$productoKey])){
			return ;
		}	
		
		$negocio = $this->productos[$productoKey]->getNegocio();
			
		unset( $this->productos[$productoKey] );	
		unset( $this->session->productosCarrito[$productoKey] );		
		
		return $this->info($negocio->idNegocio);
		
	}
	
	public function eliminarPromocion( $promoKey )
	{
		
		if ( ! isset($this->promociones[$promoKey])){
			return ;	
		}	

		$negocio = $this->promociones[$promoKey]->getNegocio();
		
		unset( $this->promociones[$promoKey] );	
		unset( $this->session->promocionesCarrito[$promoKey] );		
		
		return $this->info($negocio->idNegocio);
		
	}
	
	public function actualizarProducto( $productoKey, $cantidad )
	{
		
		if ( ! isset($this->productos[$productoKey])){
			return ;
		}	
		
		$producto = $this->productos[$productoKey];
		$producto->cantidad = $cantidad;
		$negocio = $producto->getNegocio();
			
		return $this->info($negocio->idNegocio);
		
	}
	
	public function actualizarPromocion( $promoKey, $cantidad )
	{
		
		if ( ! isset($this->promociones[$promoKey])){
			return ;	
		}	
		
		$promocion = $this->promociones[$promoKey];
		$promocion->cantidad = $cantidad;
		$negocio = $promocion->getNegocio();
			
		return $this->info($negocio->idNegocio);
		
	}
	
	public function getTotal(){
		
		$total = 0;
		
		foreach ( $this->productos as $producto ){
			$total+= $producto->getPrecioTotal();
		}
		
		foreach ( $this->promociones as $promocion ){
			$total+= $promocion->getPrecioTotal();
		}
		
		return $total;
	}
	
	public function getTotalNegocio( $idNegocio ){
		
		$total = 0;
		
		foreach ( $this->productos as $producto ){
			if ( $producto->idNegocio == $idNegocio){
				$total+= $producto->getPrecioTotal();
			}
		}
		
		foreach ( $this->promociones as $promocion ){
			if ( $promocion->idNegocio == $idNegocio){
				$total+= $promocion->getPrecioTotal( );
			}
		}
		
		return $total;
	}
	
	public function info( $idNegocio )
	{
		return array(
			'precioTotal' => number_format($this->getTotal(), 2),
			'precioTotalNegocio' => number_format($this->getTotalNegocio( $idNegocio ), 2),
			'cantidadTotal' => $this->cantidadTotal( )
		);
	}
	
	public function getNegocios()
	{
		$collection = Delivery_Model_Factory::collection('Negocios');
	
		foreach ($this->productos as $producto){
		
			$collection->append( $producto->getNegocio() );
		
		}
		
		foreach ($this->promociones as $promocion){
		
			$collection->append( $promocion->getNegocio() );
		
		} 
		
		return $collection;
	}
	
	
	
	protected function _getIds( $array_keys )
	{
		$keys = array();
		
		foreach ( $array_keys as $k ){
		
			if ( strpos	($k, "-") ){
			    
				$keys[] = current(explode("-", $k));
			} else {
				$keys[] = $k;
			}
		}
		
		return array_unique( $keys );
	} 
	
}
	